package ${projectDomain}.adapter.system;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiConstructor;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import ${projectDomain}.adapter.BaseAdapter;
import ${projectDomain}.mapper.system.api.field.SystemApiFieldExtendMapper;
import ${projectDomain}.mapper.system.api.field.SystemApiFieldMapper;
import ${projectDomain}.pojo.dao.sql.Sql;
import ${projectDomain}.pojo.dao.system.api.constructor.SystemApiConstructorInsertBatchItemDo;
import ${projectDomain}.pojo.dao.system.api.field.SystemApiFieldDataDo;
import ${projectDomain}.pojo.dao.system.api.field.SystemApiFieldDeleteDo;
import ${projectDomain}.pojo.dao.system.api.field.SystemApiFieldInsertBatchDo;
import ${projectDomain}.pojo.dao.system.api.field.SystemApiFieldInsertBatchItemDo;
import ${projectDomain}.pojo.dao.system.api.field.SystemApiFieldSearchDo;
import ${projectDomain}.pojo.dao.system.api.field.SystemApiFieldSingleDo;
import ${projectDomain}.pojo.dao.system.api.method.SystemApiMethodInsertBatchItemDo;
import com.unswift.utils.DateUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;

@Component
@Api(value="类字段api公共服务-此bean可以被任何Service引用", author="unswift", date="2023-09-06", version="1.0.0")
public class SystemApiFieldAdapter extends BaseAdapter{
	
	@Autowired
	@ApiField("类字段api数据库操作对象")
	private SystemApiFieldMapper systemApiFieldMapper;
	
	@Autowired
	@ApiField("类字段api数据库扩展操作对象")
	private SystemApiFieldExtendMapper systemApiFieldExtendMapper;
	
	@ApiMethod(value="获取类字段api数据库操作对象", returns=@ApiField("数据库操作对象"))
	public SystemApiFieldMapper getMapper(){
		return systemApiFieldMapper;
	}
	
	@ApiMethod(value="获取类字段api模块名称", returns=@ApiField("模块名称"))
	public String getModule(){
		return "systemApiField";
	}
	
	@ApiMethod(value="根据主键查询单个对象", params=@ApiField("主键"), returns=@ApiField("主键匹配的对象"))
	public SystemApiFieldDataDo findById(Long id){
		return this.findSingle(new SystemApiFieldSingleDo(id, null));
	}
	
	@ApiMethod(value="根据主键列表查询列表对象", params=@ApiField("主键列表"), returns=@ApiField("主键列表匹配的列表对象"))
	public List<SystemApiFieldDataDo> findByIds(List<Long> idList){
		return this.findList(new SystemApiFieldSearchDo(idList));
	}
	
	@ApiMethod(value="根据查询对象查询首个对象", params={@ApiField("查询对象"), @ApiField("查询到多个是否抛出异常，可以传入指定提示语，如果提示语为空，则不提示，总的提示与格式：根据%s查询到多条数据，只需要传递%s部分即可")}, returns=@ApiField("首个对象"))
	public SystemApiFieldDataDo findFirst(SystemApiFieldSearchDo search, String multipleException){
		List<SystemApiFieldDataDo> list=this.findList(search);
		if(ObjectUtils.isEmpty(list)){
			return null;
		}
		if(ObjectUtils.isNotEmpty(multipleException)){
			ExceptionUtils.trueException(list.size()>1, "multiple.data.found", multipleException);
		}
		return list.get(0);
	}
	
	@ApiMethod(value="将java字段反射转为字段对象", params = {@ApiField("java字段反射列表"), @ApiField("关联的id"), @ApiField("关联的数据表")})
    public List<SystemApiFieldInsertBatchItemDo> handleClassFieldList(List<Field> fieldList, long relationId, String relationTable) {
        SystemApiFieldDeleteDo delete=new SystemApiFieldDeleteDo();
        Sql sql=Sql.createSql();
        sql.addWhere(Sql.LOGIC_AND, "relation_id_", Sql.COMPARE_EQUAL, relationId);
        sql.addWhere(Sql.LOGIC_AND, "relation_table_", Sql.COMPARE_EQUAL, Sql.sqlValue(relationTable));
        delete.setSql(sql);
        this.deleteReal(delete);
		
		if(ObjectUtils.isNotEmpty(fieldList)) {
            List<SystemApiFieldInsertBatchItemDo> insertList=new ArrayList<SystemApiFieldInsertBatchItemDo>();
            SystemApiFieldInsertBatchItemDo insert;
            ApiField fieldAnno;
            int sort=1;
            for (Field field : fieldList) {
                fieldAnno = field.getAnnotation(ApiField.class);
                if(ObjectUtils.isEmpty(fieldAnno)) {
                    continue;
                }
                insert=new SystemApiFieldInsertBatchItemDo();
                insert.setRelationId(relationId);
                insert.setRelationTable(relationTable);
                insert.setScene("field");
                insert.setFieldComment(fieldAnno.value());
                insert.setFieldName(field.getName());
                insert.setFieldType(field.getType().getName());
                insert.setModifiers(Modifier.toString(field.getModifiers()));
                insert.setRule(fieldAnno.rule());
                insert.setRequired(fieldAnno.required());
                insert.setAuthor(fieldAnno.author());
                insert.setDate(DateUtils.parse(fieldAnno.date(), "yyyy-MM-dd"));
                insert.setDeprecated(ObjectUtils.isNotEmpty(field.getAnnotation(Deprecated.class)));
                insert.setSort(sort);
                insert.setFieldAnno(fieldAnno);
                insertList.add(insert);
                sort++;
            }
            if(ObjectUtils.isNotEmpty(insertList)) {
                this.saveBatch(new SystemApiFieldInsertBatchDo(insertList), false);
            }
            return insertList;
        }
        return null;
    }
	
	@ApiMethod(value="根据构造函数对象，处理构造函数的参数", params = {@ApiField("构造函数列表")}, returns = @ApiField("构造函数对象列表"))
    public List<SystemApiFieldInsertBatchItemDo> handleConstructorParam(List<SystemApiConstructorInsertBatchItemDo> constructorList) {
		if(ObjectUtils.isNotEmpty(constructorList)) {
            List<SystemApiFieldInsertBatchItemDo> insertList=new ArrayList<SystemApiFieldInsertBatchItemDo>();
            SystemApiFieldInsertBatchItemDo insert;
            Constructor<?> constructor;
            ApiConstructor constructorAnno;
            ApiField[] paramComments;
            Parameter[] parameters;
            int sort=1;
            for (SystemApiConstructorInsertBatchItemDo constructorDo : constructorList) {
                constructor=constructorDo.getConstructor();
                constructorAnno=constructorDo.getConstructorAnno();
                paramComments=constructorAnno.params();
                parameters = constructor.getParameters();
                if(ObjectUtils.isEmpty(parameters)) {
                    continue;
                }
                int parametersLength = parameters.length;
                ExceptionUtils.empty(paramComments, "number.of.parameters.does.not.match", constructor.getName()+"构造函数", parametersLength, 0);
                int paramCommentLength = paramComments.length;
                logger.error(constructor.getDeclaringClass()+"."+constructor.getName());
                ExceptionUtils.notEquals(parametersLength, paramCommentLength, "number.of.parameters.does.not.match", constructor.getName()+"构造函数", parametersLength, paramCommentLength);
                sort=1;
                for (int i = 0; i < parameters.length; i++) {
                    insert=new SystemApiFieldInsertBatchItemDo();
                    insert.setRelationId(constructorDo.getId());
                    insert.setRelationTable("system_api_constructor_");
                    insert.setScene("param");
                    insert.setFieldComment(paramComments[i].value());
                    insert.setFieldName(parameters[i].getName());
                    insert.setFieldType(parameters[i].getType().getName());
                    insert.setModifiers(Modifier.toString(parameters[i].getModifiers()));
                    insert.setDeprecated(ObjectUtils.isNotEmpty(parameters[i].getAnnotation(Deprecated.class)));
                    insert.setRule(paramComments[i].rule());
                    insert.setRequired(paramComments[i].required());
                    insert.setAuthor(paramComments[i].author());
                    insert.setDate(DateUtils.parse(paramComments[i].date(), "yyyy-MM-dd"));
                    insert.setSort(sort);
                    insert.setFieldAnno(paramComments[i]);
                    insertList.add(insert);
                    sort++;
                }
            }
            if(ObjectUtils.isNotEmpty(insertList)) {
                this.saveBatch(new SystemApiFieldInsertBatchDo(insertList), false);
            }
            return insertList;
        }
        return null;
    }
	
	@ApiMethod(value="根据方法对象，处理方法的参数", params = {@ApiField("方法对象列表")}, returns = @ApiField("类方法对象列表"))
    public List<SystemApiFieldInsertBatchItemDo> handleMethod(List<SystemApiMethodInsertBatchItemDo> methodList) {
        if(ObjectUtils.isNotEmpty(methodList)) {
            List<SystemApiFieldInsertBatchItemDo> insertList=new ArrayList<SystemApiFieldInsertBatchItemDo>();
            SystemApiFieldInsertBatchItemDo insert;
            Method method;
            ApiMethod methodAnno;
            ApiField[] paramComments;
            ApiField returnComment;
            Parameter[] parameters;
            Class<?> returnType;
            int sort=1;
            for (SystemApiMethodInsertBatchItemDo methodDo : methodList) {
                method=methodDo.getMethod();
                methodAnno=methodDo.getMethodAnno();
                paramComments=methodAnno.params();
                parameters = method.getParameters();
                if(ObjectUtils.isEmpty(parameters)) {
                    continue;
                }
                int parametersLength = parameters.length;
                logger.error(method.getDeclaringClass()+"."+method.getName());
                ExceptionUtils.empty(paramComments, "number.of.parameters.does.not.match", method.getDeclaringClass()+"."+method.getName(), parametersLength, 0);
                int paramCommentLength = paramComments.length;
                logger.error(method.getDeclaringClass()+"."+method.getName());
                ExceptionUtils.notEquals(parametersLength, paramCommentLength, "number.of.parameters.does.not.match", method.getDeclaringClass()+"."+method.getName(), parametersLength, paramCommentLength);
                sort=1;
                for (int i = 0; i < parameters.length; i++) {
                    insert=new SystemApiFieldInsertBatchItemDo();
                    insert.setRelationId(methodDo.getId());
                    insert.setRelationTable("system_api_method_");
                    insert.setScene("param");
                    insert.setFieldComment(paramComments[i].value());
                    insert.setFieldName(parameters[i].getName());
                    insert.setFieldType(parameters[i].getType().getName());
                    insert.setModifiers(Modifier.toString(parameters[i].getModifiers()));
                    insert.setDeprecated(ObjectUtils.isNotEmpty(parameters[i].getAnnotation(Deprecated.class)));
                    insert.setRule(paramComments[i].rule());
                    insert.setRequired(paramComments[i].required());
                    insert.setAuthor(paramComments[i].author());
                    insert.setDate(DateUtils.parse(paramComments[i].date(), "yyyy-MM-dd"));
                    insert.setSort(sort);
                    insert.setFieldAnno(paramComments[i]);
                    insertList.add(insert);
                    sort++;
                }
                returnComment=methodAnno.returns();
                returnType=method.getReturnType();
                insert=new SystemApiFieldInsertBatchItemDo();
                insert.setRelationId(methodDo.getId());
                insert.setRelationTable("system_api_method_");
                insert.setScene("return");
                insert.setFieldComment(returnComment.value());
                insert.setFieldType(returnType.getName());
                insert.setRule(returnComment.rule());
                insert.setRequired(returnComment.required());
                insert.setAuthor(returnComment.author());
                insert.setDate(DateUtils.parse(returnComment.date(), "yyyy-MM-dd"));
                insert.setSort(sort);
                insert.setFieldAnno(returnComment);
                insertList.add(insert);
            }
            if(ObjectUtils.isNotEmpty(insertList)) {
                this.saveBatch(new SystemApiFieldInsertBatchDo(insertList), false);
            }
            return insertList;
        }
        return null;
    }
	
	@ApiMethod(value="根据类Api数据id删除字段、构造函数、方法的版本信息", params = @ApiField("类API数据id"))
	public void deleteByClassId(long apiClassId) {
        //删除构造函数字段
		SystemApiFieldDeleteDo delete=new SystemApiFieldDeleteDo();
        Sql sql=Sql.createSql();
        Sql searchSql=Sql.createSql();
        searchSql.addSelect("id_");
        searchSql.addFrom("system_api_constructor_");
        searchSql.addWhere(Sql.LOGIC_AND, "api_class_id_", Sql.COMPARE_EQUAL, apiClassId);
        sql.addWhere(Sql.LOGIC_AND, "relation_id_", Sql.COMPARE_IN, searchSql.toSql());
        sql.addWhere(Sql.LOGIC_AND, "relation_table_", Sql.COMPARE_EQUAL, Sql.sqlValue("system_api_constructor_"));
        delete.setSql(sql);
        this.deleteReal(delete);
        //删除方法字段
        sql=Sql.createSql();
        searchSql=Sql.createSql();
        searchSql.addSelect("id_");
        searchSql.addFrom("system_api_method_");
        searchSql.addWhere(Sql.LOGIC_AND, "api_class_id_", Sql.COMPARE_EQUAL, apiClassId);
        sql.addWhere(Sql.LOGIC_AND, "relation_id_", Sql.COMPARE_IN, searchSql.toSql());
        sql.addWhere(Sql.LOGIC_AND, "relation_table_", Sql.COMPARE_EQUAL, Sql.sqlValue("system_api_method_"));
        delete.setSql(sql);
        this.deleteReal(delete);
	}
}
